RealtimeChart   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 188
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 15
eloc 151
dl 0
loc 188
rs 10
c 0
b 0
f 0

3 Functions

Rating   Name   Duplication   Size   Complexity  
A componentWillUnmount 0 5 1
B render 0 45 1
F componentDidMount 0 116 13
1
import React, { Component } from 'react';
2
import { Line } from 'react-chartjs-2';
3
import range from 'lodash/range';
4
import { Card, CardHeader, CardBody, ListGroup, ListGroupItem } from 'reactstrap';
5
import { rgbaColor } from '../../../helpers/utils';
6
import { withTranslation } from 'react-i18next';
7
import { v4 as uuid } from 'uuid';
8
import { APIBaseURL } from '../../../config';
9
import { getCookieValue, floatFormatter } from '../../../helpers/utils';
10
import { toast } from 'react-toastify';
11
12
const dividerBorder = '1px solid rgba(255, 255, 255, 0.15)';
13
const listItemBorderColor = 'rgba(255, 255, 255, 0.05)';
14
15
const chartOptions = {
16
  legend: { display: false },
17
  scales: {
18
    yAxes: [
19
      {
20
        display: true,
21
        stacked: false
22
      }
23
    ],
24
    xAxes: [
25
      {
26
        stacked: false,
27
        ticks: { display: false },
28
        categoryPercentage: 1.0,
29
        gridLines: {
30
          color: rgbaColor('#fff', 0.1),
31
          display: true
32
        }
33
      }
34
    ]
35
  }
36
};
37
38
class RealtimeChart extends Component {
39
  _isMounted = false;
40
  refreshInterval;
41
  refreshTimeout;
42
  state = {
43
    trendLog: [],
44
    currentEnergyValue: undefined,
45
    energyValuePointName: undefined,
46
    chartData: {
47
      labels: range(1, 61),
48
      datasets: [
49
        {
50
          label: '',
51
          backgroundColor: rgbaColor('#fff', 0.3)
52
        }
53
      ]
54
    },
55
    pointList: []
56
  };
57
58
  componentWillUnmount() {
59
    this._isMounted = false;
60
    clearInterval(this.refreshInterval);
61
    clearTimeout(this.refreshTimeout);
62
  }
63
64
  componentDidMount() {
65
    this._isMounted = true;
66
    const { t } = this.props;
67
    // fetch meter realtime data at the first time
68
    let isResponseOK = false;
69
    fetch(APIBaseURL + '/reports/meterrealtime?meterid=' + this.props.meterId, {
70
      method: 'GET',
71
      headers: {
72
        'Content-type': 'application/json',
73
        'User-UUID': getCookieValue('user_uuid'),
74
        Token: getCookieValue('token')
75
      },
76
      body: null
77
    })
78
      .then(response => {
79
        if (response.ok) {
80
          isResponseOK = true;
81
        }
82
        return response.json();
83
      })
84
      .then(json => {
85
        if (isResponseOK) {
86
          console.log(json);
87
          let length = json['energy_value']['values'].length;
88
          let trendLog =
89
            length > 60 ? json['energy_value']['values'].slice(length - 60, length) : json['energy_value']['values'];
90
          let currentEnergyValue = undefined;
91
          let energyValuePointName = json['energy_value']['name'];
92
          let pointList = [];
93
          let chartData = Object.assign(this.state.chartData);
94
          chartData.labels = trendLog.length > 60 ? range(1, 61) : range(1, trendLog.length + 1);
95
          if (trendLog.length > 0) {
96
            currentEnergyValue = trendLog[trendLog.length - 1];
97
          }
98
          json['parameters']['names'].forEach((currentName, index) => {
99
            let pointItem = {};
100
            pointItem['name'] = currentName;
101
            pointItem['value'] = undefined;
102
            let currentValues = json['parameters']['values'][index];
103
            if (currentValues.length > 0) {
104
              pointItem['value'] = currentValues[currentValues.length - 1];
105
            }
106
            pointList.push(pointItem);
107
          });
108
          if (this._isMounted) {
109
            this.setState({
110
              chartData: chartData,
111
              trendLog: trendLog,
112
              currentEnergyValue: floatFormatter(currentEnergyValue),
113
              energyValuePointName: energyValuePointName,
114
              pointList: pointList
115
            });
116
          }
117
        } else {
118
          toast.error(t(json.description));
119
        }
120
      })
121
      .catch(err => {
122
        console.log(err);
123
      });
124
125
    //fetch meter realtime data at regular intervals
126
    this.refreshInterval = setInterval(() => {
127
      let isResponseOK = false;
128
      fetch(APIBaseURL + '/reports/meterrealtime?meterid=' + this.props.meterId, {
129
        method: 'GET',
130
        headers: {
131
          'Content-type': 'application/json',
132
          'User-UUID': getCookieValue('user_uuid'),
133
          Token: getCookieValue('token')
134
        },
135
        body: null
136
      })
137
        .then(response => {
138
          if (response.ok) {
139
            isResponseOK = true;
140
          }
141
          return response.json();
142
        })
143
        .then(json => {
144
          if (isResponseOK) {
145
            console.log(json);
146
            let trendLog = json['energy_value']['values'];
147
            let currentEnergyValue = undefined;
148
            let energyValuePointName = json['energy_value']['name'];
149
            let pointList = [];
150
            if (trendLog.length > 0) {
151
              currentEnergyValue = trendLog[trendLog.length - 1];
152
            }
153
            json['parameters']['names'].forEach((currentName, index) => {
154
              let pointItem = {};
155
              pointItem['name'] = currentName;
156
              pointItem['value'] = undefined;
157
              let currentValues = json['parameters']['values'][index];
158
              if (currentValues.length > 0) {
159
                pointItem['value'] = currentValues[currentValues.length - 1];
160
              }
161
              pointList.push(pointItem);
162
            });
163
            if (this._isMounted) {
164
              this.setState({
165
                trendLog: trendLog,
166
                currentEnergyValue: currentEnergyValue,
167
                energyValuePointName: energyValuePointName,
168
                pointList: pointList
169
              });
170
            }
171
          } else {
172
            toast.error(t(json.description));
173
          }
174
        })
175
        .catch(err => {
176
          console.log(err);
177
        });
178
    }, (60 + Math.floor(Math.random() * Math.floor(10))) * 1000); // use random interval to avoid paralels requests
179
  }
180
181
  render() {
182
    const { t } = this.props;
183
    const chartData = {
184
      ...this.state.chartData,
185
      datasets: [
186
        {
187
          ...this.state.chartData.datasets[0],
188
          data: this.state.trendLog
189
        }
190
      ]
191
    };
192
193
    return (
194
      <Card className="h-100 bg-gradient">
195
        <CardHeader className="bg-transparent">
196
          <h5 className="text-white">{this.props.meterName}</h5>
197
          <div className="real-time-user display-4 font-weight-normal text-white">{this.state.currentEnergyValue}</div>
198
        </CardHeader>
199
        <CardBody className="text-white fs--1">
200
          <p className="pb-2" style={{ borderBottom: dividerBorder }}>
201
            {t('Trend in the last hour of Energy Value Point')} {this.state.energyValuePointName}
202
          </p>
203
          <Line data={chartData} options={chartOptions} width={10} height={4} />
204
          <ListGroup flush className="mt-4">
205
            <ListGroupItem
206
              className="bg-transparent d-flex justify-content-between px-0 py-1 font-weight-semi-bold border-top-0"
207
              style={{ borderColor: listItemBorderColor }}
208
            >
209
              <p className="mb-0">{t('Operating Characteristic Curve')}</p>
210
              <p className="mb-0">{t('Realtime Value')}</p>
211
            </ListGroupItem>
212
            {this.state.pointList.map(pointItem => (
213
              <ListGroupItem
214
                key={uuid()}
215
                className="bg-transparent d-flex justify-content-between px-0 py-1"
216
                style={{ borderColor: listItemBorderColor }}
217
              >
218
                <p className="mb-0">{pointItem['name']}</p>
219
                <p className="mb-0">{pointItem['value']}</p>
220
              </ListGroupItem>
221
            ))}
222
          </ListGroup>
223
        </CardBody>
224
      </Card>
225
    );
226
  }
227
}
228
229
export default withTranslation()(RealtimeChart);
230